package top.huiwow;


import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import top.huiwow.commands.GetItemCommand;
import top.huiwow.commands.PlayerStatCommand;
import top.huiwow.commands.SpawnEntityCommand;
import top.huiwow.commands.UncontrolStatsCommand;
import top.huiwow.entity.EntityManager;
import top.huiwow.entity.Negromancer;
import top.huiwow.entity.Nicron;
import top.huiwow.items.Hyperion;
import top.huiwow.items.ItemStats;
import top.huiwow.items.NicronHelmet;
import top.huiwow.items.Terminator;
import top.huiwow.listeners.EntityListener;
import top.huiwow.listeners.PlayerListener;
import top.huiwow.managers.GamePlayer;
import top.huiwow.managers.GamePlayerManager;
import top.huiwow.managers.HealthManager;
import top.huiwow.managers.ItemManager;
import top.huiwow.utils.ActionBar;
import top.huiwow.utils.ItemBuilder;
import top.huiwow.utils.MathUtils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class GameCore extends JavaPlugin {
    public static ItemStats emptyStatsModifier = new ItemStats();
    static Random random;
    public static GameCore INSTANCE;
    public Set<Player> sentNotEnoughMana = new HashSet<>();
    private PluginManager pluginManager;
    private HealthManager healthManager;
    private GamePlayerManager gamePlayerManager;
    private PlayerListener playerListener;
    private EntityListener entityListener;
    private EntityManager entityManager;
    private ItemManager itemManager;

    public static GameCore getInstance() {
        return INSTANCE;
    }

    public static Random getRandom() {
        return random;
    }

    public static FixedMetadataValue getFixedMetadataValue() {
        return new FixedMetadataValue(GameCore.getInstance(), true);
    }

    public static String getMetadataValue() {
        return "akaishi";
    }

    public HealthManager getHealthManager() {
        return healthManager;
    }

    public GamePlayerManager getGamePlayerManager() {
        return gamePlayerManager;
    }

    public PlayerListener getPlayerListener() {
        return playerListener;
    }

    public EntityListener getEntityListener() {
        return entityListener;
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public ItemManager getItemManager() {
        return itemManager;
    }

    @Override
    public void onEnable() {
        INSTANCE = this;
        random = new Random();
        this.pluginManager = this.getServer().getPluginManager();
        healthManager = new HealthManager();
        gamePlayerManager = new GamePlayerManager();
        playerListener = new PlayerListener();
        entityListener = new EntityListener();
        entityManager = new EntityManager();
        itemManager = new ItemManager();
        registerEvents(
                healthManager,
                gamePlayerManager,
                playerListener,
                entityListener
        );
        entityManager.registerEntity(new Nicron(),new Negromancer());
        itemManager.registerItem(
                new Hyperion(),
                new Terminator(),
                new NicronHelmet()
        );
        setExecutor("spawnakaishi", new SpawnEntityCommand());
        setExecutorAndTabCompleter("playerstat", new PlayerStatCommand());
        setExecutor("getitem", new GetItemCommand());
        setExecutorAndTabCompleter("uncontrolstats", new UncontrolStatsCommand());
        Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this::tickActionBar, 5, 5);
        Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this::regenMana, 20, 20);
        Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this::tickStatsUpdate, 30, 30);
        System.out.println("-----------------------------------");
        System.out.println("-----------AKAISHI LOADED----------");
        System.out.println("-----------------------------------");
        System.out.println("MADE WITH LOVE BY 吃我的是!");
    }

    void regenMana() {
        for (GamePlayer gamePlayer : gamePlayerManager.gamePlayers.values()) {
            int mana = gamePlayer.getMana();
            int intelligence = gamePlayer.getIntelligence();
            gamePlayer.setMana(Math.min(((int) (mana + intelligence * 0.02)), intelligence));
        }
    }

    public void tickActionBar() {
        for (Player player : Bukkit.getOnlinePlayers()) {
            if (sentNotEnoughMana.contains(player)) {
                continue;
            }
            GamePlayer gamePlayer = getGamePlayerManager().get(player.getUniqueId());
            String health = ChatColor.RED.toString() + ChatColor.BOLD + (MathUtils.round_half_up(player.getHealth(), 1)) + "/" + player.getMaxHealth() + "❤";
            String defense = ChatColor.GREEN.toString() + ChatColor.BOLD + gamePlayer.getDefense() + "❈ Defense";
            //String strength= ChatColor.DARK_RED.toString()+ChatColor.BOLD +gamePlayer.getStrength()+" "+ ChatColor.BOLD+"❁Strength";
            String mana = ChatColor.AQUA.toString() + ChatColor.BOLD + gamePlayer.getMana() + "/" + gamePlayer.getIntelligence() + ChatColor.BOLD + "✎" + " Mana";
            ActionBar.send(player, ActionBar.joinActionBar(health, defense, mana));
        }
    }

    public void tickStatsUpdate() {
        for (GamePlayer gamePlayer : gamePlayerManager.gamePlayers.values()) {
            if (gamePlayer.controlledStats) {
                continue;
            }
            Player player = gamePlayer.getPlayer();
            int intelligence = ItemBuilder.getTotalStatsModifier(player).intelligence;
            gamePlayer.setIntelligence(100 + intelligence);

            int strength = ItemBuilder.getTotalStatsModifier(player).strength;
            gamePlayer.setStrength(strength);

            int defense = ItemBuilder.getTotalStatsModifier(player).defense;
            gamePlayer.setDefense(defense);

            int speed = ItemBuilder.getTotalStatsModifier(player).speed;
            gamePlayer.setSpeed(100 + speed);

            int critChance = ItemBuilder.getTotalStatsModifier(player).critChance;
            if (ItemBuilder.isItem(gamePlayer.getPlayer().getItemInHand(),this.itemManager.getInternalName(Terminator.class))){
                gamePlayer.setCritChance((30 + critChance)/4);
            }else {
                gamePlayer.setCritChance(30 + critChance);
            }

            int critDamage = ItemBuilder.getTotalStatsModifier(player).critDamage;
            gamePlayer.setCritDamage(critDamage);

            boolean maxHP=gamePlayer.getPlayer().getHealth()>=gamePlayer.getPlayer().getMaxHealth()*0.7;
            int health= ItemBuilder.getTotalStatsModifier(player).health;
                        gamePlayer.getPlayer().setMaxHealth(100+health);
                        if (maxHP) {
                            gamePlayer.getPlayer().setHealth(100+health);
                        }
        }
    }

    public int getOrDefaultFromConfig(String path, int defaulta) {
        int result;
        try {
            result = (int) getConfig().get(path);
        } catch (Exception e) {
            getConfig().set(path, defaulta);
            result = defaulta;
        }
        saveConfig();
        return result;
    }

    private void setExecutor(String name, CommandExecutor executor) {
        getCommand(name).setExecutor(executor);
    }

    private void setExecutorAndTabCompleter(String name, Object obj) {
        PluginCommand command = getCommand(name);

        command.setExecutor((CommandExecutor) obj);
        command.setTabCompleter((TabCompleter) obj);
    }

    public void registerEvents(Listener... listeners) {
        Arrays.stream(listeners).forEach(c -> pluginManager.registerEvents(c, this));
    }
    public void registerEvent(Listener listener) {
       pluginManager.registerEvents(listener, this);
    }

}



